/*!
 * Copyright (c) 2010 Jacob Essex
 *
 * Dual licenced under MIT or GPL 3 licneces
 * 
 * See the GPL3 or MIT files in the main directory for details
 */
function Bayes(classBoundries){

    var that = this;

    //this is the function that clasiffies how "good" an answer is.
    //TODO this was written off the top of my head
    var getGoodness = function(answer){
        return answer.UpVotes - answer.DownVotes*0.4;// + answer.Accepted*2;
    }



    //predication data needs to be rebuilt if these change
    classBoundries = classBoundries ? classBoundries : [8,4,2,0];

    var getClass = function(goodness){
        for ( var i = 0; i < classBoundries.length; i++ ){
            if ( goodness > classBoundries[i] ){
                return i;
            }
        }
        return classBoundries.length;
    }


    var tags = {}

    this.train = function(answer){
        var g = getGoodness(answer);
        var cls = getClass(g);

        answer.QuestionTags.forEach(function(tag){
            if ( tags[tag] == undefined ){
                tags[tag] = {_count:0}
            }
            if ( tags[tag][cls] == undefined ){
                tags[tag][cls] =  0;
            }
            tags[tag][cls]++;
            tags[tag]._count++;
        });
        

    }

    /**
     * @param nc the number of items with the class that we want
     * @param n the total number of items
     * @param s the number of possible classes (I think?)
     */ 
    var mEst = function(nc, n, s){
        return (nc + 1)/(n + 5);
        return nc;
    }


    var doGuess = function(dataArray){
        var curV = 0;
        var curCls = classBoundries.length - 1;

        classBoundries.forEach(function(cls){
            var v = 1;
            dataArray.forEach(function(data){
                data.tags.forEach(function(tag){
                    if ( tags[tag] === undefined ){
                        v *= data.unknown;
                    }else{
                        v *= mEst( tags[tag][cls] === undefined ? 0: tags[tag][cls],
                                   tags[tag]._count, classBoundries.length );
                    }
                });
                v *= data.pvalue;
            });
            if ( v >= curV ){
                curV = v;
                curCls = cls;
            }
        });
        return {min:curCls, est:curV};
    }

    this.guess = function(question){
        var cls = doGuess([ 
                          {tags:question.QuestionTags, pvalue:0.5, unknown:0.2},
                          {tags:question.InferredTags, pvalue:0.3, unknown:0.8}
                        ]); 
        return cls; 
    }
}
